<?php

/* Communical test script
 * Michael Greene
 *
 * This is mostly just a proof of concept for reading Google Calendar information
 * This will evolve into a full-fledged social event calendar application
 *
 * Definitely use .htaccess and URL re-writing for pretty URLs
 */
 
// Page load times for testing only
$time = microtime();
$time = explode(" ", $time);
$time = $time[1] + $time[0];
$start = $time;
//

require_once 'Zend/Cache.php';
require_once 'Zend/Date.php';
require_once 'Zend/Gdata.php';
require_once 'Zend/Gdata/Calendar.php';
require_once 'Zend/Gdata/ClientLogin.php';
require_once 'Zend/Http/Client.php';

require_once 'conf/conf.ini';

$mapsAPIKey = $cconfig['mapsAPIKey'];
$mapsJS = '<script src="http://maps.google.com/maps?file=api&v=2&key=' . $mapsAPIKey . '" type="text/javascript"></script>';
?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
	<title>RADiCAL Test</title>
	<?php 
		echo "\t" . $mapsJS;
		printCSS();
	?>
	<script type="text/javascript">
		//<![CDATA[
		var map;
		function load()
		{
			if (GBrowserIsCompatible()) {
				//var map = new GMap2(document.getElementById("map"));
				map = new GMap2(document.getElementById("map"));
				map.addControl(new GSmallMapControl());
				map.addControl(new GMapTypeControl());
				map.setCenter(new GLatLng(42.967477,-85.654092), 14); <?php // Change to be variable based on config ?>
				//var point = new GLatLng(42.967477,-85.654092);
				//map.addOverlay(new GMarker(point));
				//map.addOverlay(createMarker(point, "test");
				
				var point = new GLatLng(42.967477,-85.654092);
				map.addOverlay(createMarker(point, 2));
			}
		}
		
		// Creates a marker at the given point with the given number label
		function createMarker(point, number) {
		var marker = new GMarker(point);
		GEvent.addListener(marker, "click", function() {
			marker.openInfoWindowHtml("Marker #<b>" + number + "</b>");
			} );
		return marker;
		}
		//]]>
	</script>
</head>
<body onLoad="load()" onunload="GUnload()">
<?php
/*
 * Get parameters from the URL
 */
 
 // TODO!!!!!
 
 // Abilities: future only, all, by month, individual event, by tag - these could just be different php files for some
 

/*
 * Set up the data cache
 */
$frontendOptions = array(
	'lifeTime' => 300, // 7200 seconds (2 hours)
	'automaticSerialization' => true
);
$backendOptions = array(
	'cacheDir' => './tmp/',
	'fileNamePrefix' => 'data'
);

$dataCache = Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);

/*
 * Set up the output cache
 */
$frontendOptions = array(
	'lifeTime' => 30,
	'automaticSerialization' => false
);
$backendOptions = array(
	'cacheDir' => './tmp/',
	'fileNamePrefix' => 'output'
);

$outputCache = Zend_Cache::factory('Output', 'File', $frontendOptions, $backendOptions);

/*
 * Set up the geocoding cache
 *   This should only be used in calls to function geocode()
 */
$frontendOptions = array(
	'lifeTime' => 7200, // change to null when I know it works
	'automaticSerialization' => false
);
$backendOptions = array(
	'cacheDir' => './tmp/',
	'fileNamePrefix' => 'geo'
);

$geoCache = Zend_Cache::factory('Function', 'File', $frontendOptions, $backendOptions);

/*
 * Check data cache for parameter-based feed, otherwise get feed from google
 */
 
if (!$feed = $dataCache->load('composite')) {
	echo '<span class="warning">Data cache miss!  This page should load faster next time.</span>'."\n\n";
	try {
		// Information for later
		$calURI = 'http://www.google.com/calendar/render?cid=radical%40g-rad.org';
		$iCalURI = 'http://www.google.com/calendar/ical/radical%40g-rad.org/public/basic.ics';
		
		// Google account credentials
		$email = $cconfig['calEmail'];
		$passwd = $cconfig['calPassword'];
		
		// Login with the account credentials
		$client = Zend_Gdata_ClientLogin::getHttpClient($email, $passwd, 'cl');
		
		// Request the account's calendar
		$cal = new Zend_Gdata_Calendar($client);
		
		// Not sure why this is needed
		$cal->setUser('default');
		
		// Show all events private and public
		$cal->setVisibility('private');
		
		// Options: {composite, full, free-busy}
		$cal->setProjection('composite');
		
		// $cal->futureevents = 'true' // if only want all future events
		
		// Order
		$cal->setOrderby('starttime');
		
		// Beginning and end dates, both optional, in YYYY-MM-DD format
		$cal->setStartMin('2007-01-01');
		$cal->setStartMax('2007-03-01');
		
		// Retrieve the feed from the server and store it in the cache
		$feed = $cal->getCalendarFeed();
		$dataCache->save($feed, 'composite');
	} 
	catch(Zend_Gdata_Exception $ex) {
		echo '<h2>Oh No!  There was a problem with the data:</h2>';
		die($ex->getMessage() . '<hr>' . $ex->getTraceAsString());
	} catch(Zend_Feed_Exception $ex) {
		echo '<h2>Oh No!  There was a problem with the feed:</h2>';
		die($ex->getMessage() . '<hr>' . $ex->getTraceAsString());
	} catch(Exception $ex) {
		echo '<h2>Oh No!  There was an unknown error.  See if this helps:</h2>';
		die($ex->getMessage() . '<hr>' . $ex->getTraceAsString());
	}
}
else {
	// Cache hit, don't need to do anything (already got the data)
}
?>
<div id="map" class="comment">Map</div>
<?php

/*
 * Display output, parsing feed and generating output if not cached
 */
if(!$outputCache->start('composite')) {
	$comments = 'gd:comments';
	$when = 'gd:when';
	$where = 'gd:where';
	
	echo '<h1><a href="' . $calURI . '">RADiCAL</a> has ' . $feed->count() . ' 	events.</h1>' . "\n";
	echo '<p><a href="' . $iCalURI . '"><img src="http://icalshare.com/layout/iCalShare/theme-images/subscribe.gif" /> Subscribe to the iCal</a></p>';

	foreach ($feed as $entry) {
		echo '<div class="event">';
		
		$links = $entry->link();
		$publicLinkURI = $links[0]->getAttribute('href');
		
		echo '<h2>' . '<a href="' . $publicLinkURI . '">' . $entry->title() . "</a></h2>\n";
		
		$content = $entry->content();
		$tagDelimiter = 'tags: ';
		$tagStart = strripos($content, $tagDelimiter);
		if ($tagStart !== false) {
			$tags = substr($content, $tagStart + strlen($tagDelimiter));
			$content = substr($content, 0, $tagStart);
			$tags = explode(', ', $tags);
		}
		echo '<div class="content">' . "\n";
		echo breaks($content);
		echo "\n</div>\n";
		
		if ($tagStart !== false) {
			echo '<span class="detail">Tags:</span>';
			foreach ($tags as $tag) {	echo '<span class="tag"><a href="./tags/' . $tag . '/">' . $tag . '</a></span>';	}
		}
		
		$startDate = new Zend_Date($entry->{$when}['startTime'], Zend_Date::ISO_8601);
		$endDate = new Zend_Date($entry->{when}['endTime'], Zend_Date::ISO_8601);
	
		echo '<span class="detail">When:</span>';
		echo $startDate->toString('MMMM dd, yyyy') . ' from ' . $startDate->toString('hh:mm') . ' to ' . $endDate->toString(	'hh:mm');
		echo "\n<br>";
		
		
		$location = $entry->{$where}['valueString'];
		echo '<span class="detail">Where:</span>';
		echo $location; // hahahahahahahahahahahahahahahahahahahahahaha
		
		$delimiter = ', ';
		$addressStart = strpos($location, $delimiter);
		if ($addressStart !== false) {
			$place = substr($location, 0, $addressStart);
			$address = substr($location, $addressStart + strlen($delimiter));
			$gc = $geoCache->call('geocode', array($address, $mapsAPIKey)); // CHANGE HOW THIS WORKS... THERE SHOULD BE A LOCATION CLASS
			// echo ' (' . $gc['latitude'] . ', ' . $gc['longitude'] . ') ';
		}
		echo mapLink($location);
		echo '<script type="text/javascript">';
		echo "var point = new GLatLng(" . $gc['longitude'] . "," . $gc['latitude'] . ");\n";
echo "var marker = createMarker(point, '<div id=\"infowindow\" style=\"white-space: nowrap;\">" . addslashes($place) . "</div>');\n";
		echo 'this["map"].addOverlay(marker);' . "\n";
		//echo "var marker = new GMarket(point);\n";
		echo "\n";
		echo '</script>';
		
		
		//echo "<i>XML version</i>";
		//print_r($entry->$comments->saveXML());
	
		
		$commentsDoc = $entry->$comments->getDOM();
		$commentEntries = $commentsDoc->getElementsByTagName("entry");
		
		if ($commentEntries->length > 0) {
			echo "<h3>" . $commentEntries->length . " Comment(s):</h3>\n";
			foreach ($commentEntries as $commentEntry) {
				echo '<div class="comment">';
				$author = $commentEntry->getElementsByTagName('author');
				$authorDetails = $author->item(0)->childNodes;
				$name = $authorDetails->item(0)->nodeValue;
				$email = $authorDetails->item(1)->nodeValue;
				$content = $commentEntry->getElementsByTagName('content')->item(0)->nodeValue;
				
				echo '<b>' . $name . '</b> (<i>' . $email . '</i>) wrote: ' . $content;
				echo '</div>';
			}
		}
		
		echo "</div>";
	} 
	echo "\n Cached time: ".time().'<br>';
	
	$outputCache->end();
}

echo "\n Current time: ".time().'<br>';

$time = microtime();
$time = explode(" ", $time);
$time = $time[1] + $time[0];
$finish = $time;
$totaltime = ($finish - $start);
printf ("This page took %f seconds to load.", $totaltime);
?>

<?php

function breaks($text) {
	$output = preg_replace("/\n/","\n<br>",$text);
	return $output;
}

function mapLink($location) {
	$delimiter = ', ';
	$addressStart = strpos($location, $delimiter);
	if ($addressStart !== false) {
		$place = substr($location, 0, $addressStart);
		$address = substr($location, $addressStart + strlen($delimiter));
		$queryString = 'near=' . $address . '&q=' . $place;
	} else {
		$queryString = $location;
	}
	$output = '<span class="mapLink"><a href="http://maps.google.com?' . htmlentities($queryString) . '"><img src="images/map_go.png"/> Map</a></span>';
	return $output;
}

function printCSS() {
	/*
	 * This is only temporary, to be replaced by a full templating system later, ideally simpler than Smarty
	 * but that could be used if it must.
	 */
	 
	echo "\t" . '<style type="text/css">';
	echo "
		body { font-family: Verdana, Arial, sans-serif; font-size: 70%; }
		img { border: 0; }
		h2 { font-variant: small-caps; letter-spacing: 3px; }
		a { text-decoration: none; }
		a:hover { text-decoration: underline; }
		div.event { margin-bottom: 10px; padding: 5px; border: 1px solid #f9a; background: #fde; }
		div.comment { margin: 5px; border: 1px solid #99f; padding: 2px; background: #ddf; }
		div#map { margin: 5px; float: right; width: 450px; height: 350px; min-height: 300px; clear: both; }
		span.mapLink { padding-left: 15px; }
		span.detail { margin: 5px 3px 0 0; font-weight: 700; display: block; clear: left; }
		span.tag { margin-left: 15px; }
		span.warning { font-weight: 700; color: red; }
		v\:* { behavior:url(#default#VML); }";
	echo "\n" . '</style>';
}

function geocode($address, $key) {
	/*
	 * Retrieves the longitude and latitude of an address from Google's geocoder
	 *   Todo: Allow socket or CURL requests later
	 *   Todo: Use XML instead of CSV and return more interesting information
	 */
	 
	$geoURI = 'http://maps.google.com/maps/geo?q=' . urlencode($address) . '&output=csv&key=' . $key;

	$handle = fopen($geoURI, "r");

	$data = fgets($handle);
	fclose($handle);
	
	if (strstr($data,'200'))
	{
		$data = explode(',',$data);
		$keyedArray = array(
			'status' => $data[0],
			'precision' => $data[1],
			'latitude' => $data[2],
			'longitude' => $data[3]
		);

		return $keyedArray;
	} else {
		echo ' !!Error geocoding: ' . $data . ' !! ';
		return null;
	}
}

?>

</body>
</html>